﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Linq;
using Calabonga.Mvc.PagedListExt;

namespace Central.Linq.Mvc {
	/// <summary>
	/// Базовый класс для ViewModel'a, который
	/// сможет использовать фильтрацию на основании QueryParams
	/// </summary>
	/// <typeparam name="TModel">модель</typeparam>
	/// <typeparam name="TViewModel">ViewModel модели должен реализовывать IPreparable</typeparam>
#if !DEBUG

	[DebuggerStepThrough]
#endif

	public abstract class PreparableViewModel<TModel, TViewModel> : IPreparableViewModel {

		/// <summary>
		/// Возращает экземпляр базового класс для ViewModel'а
		/// </summary>
		/// <param name="filters">список фильтров</param>
		protected PreparableViewModel(IList<FilterDefinition> filters) {
			if (filters == null) throw new ArgumentNullException("filters", "Список фильтров пустой!");
			this._clientFilters = filters;
		}

		/// <summary>
		/// Возращает экземпляр базового класс для ViewModel'а
		/// </summary>
		/// <param name="filters">список фильтров</param>
		/// <param name="items">Модели для запроса</param>
		/// <param name="pageindex">номер страницы</param>
		protected PreparableViewModel(IList<FilterDefinition> filters, int? pageindex, IQueryable<TModel> items)
			: this(filters) {
		}

		/// <summary>
		/// Созданные ViewModelы по заданному фильтру
		/// </summary>
		public PagedList<TViewModel> Items { get; private set; }

		[UIHint("ClientFilters")]
		public IList<FilterDefinition> ClientFilters { get { return _clientFilters; } }

		/// <summary>
		/// Инициализация менеджера свойств для сущности
		/// </summary>
		/// <returns>InfoManager</returns>
		protected abstract InfoManager InitializeInfoManager();

		/// <summary>
		/// Запуск выборки через PrepareQuery с использованием InfoManager
		/// </summary>
		/// <param name="pageindex"></param>
		/// <param name="items"></param>
		protected void MakeSelection(int? pageindex, IQueryable<TModel> items) {
			this.InitializeViewModel();
			_queryParams.Filters = new FilterManager(LogicalOperator.And, new Collection<FilterDefinition>(this._clientFilters));
			this.Items = items.AsQueryable()
				.PrepareQuery<TModel, TViewModel>(_queryParams)
				.ToPagedList(pageindex ?? 1);
		}

		private QueryParams _queryParams;

		private readonly IList<FilterDefinition> _clientFilters;

		private void InitializeViewModel() {
			this._queryParams = new QueryParams(this.InitializeInfoManager().DefaultFieldManager);
		}
	}
}